<?php

Raise::load('core.RaiseObject');
Raise::load('db.RaiseDbSqlWhere');
Raise::load('core.RaiseTypedCollection');
Raise::load('core.RaiseCollection');
Raise::load('db.RaiseDbSqlJoin');
Raise::load('db.RaiseDbSqlOrder');

/**
 * RaiseDbSqlQueryCondition class
 * contains all conditions for a SQL query
 *
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.DataAccess.Sql
 * @since 1.2
 */
class RaiseDbSqlQueryCondition extends RaiseObject {
    
    /**
     * The conditions of this statement
     * @var RaiseDbSqlWhere
     */
    private $where;

    /**
     * The row limit
     * @var integer
     */
    private $limit;

    /**
     * The result offset
     * @var integer
     */
    private $offset;

    /**
     * A collection of RaiseDbSqlJoin
     * @var RaiseTypedCollection
     */
    private $join;

    /**
     * Collection of GROUP BY fields
     * @var RaiseCollection
     */
    private $group;

    /**
     * Collection of ORDER BY fields
     * @var RaiseTypedCollection
     */
    private $order;

    /**
     * Create a new RaiseDbSqlQueryCondition
     */
    function __construct() {
        $this->join = new RaiseTypedCollection('RaiseDbSqlJoin');
        $this->group = new RaiseCollection();
        $this->order = new RaiseTypedCollection('RaiseDbSqlOrder');
        $this->where = new RaiseDbSqlWhere();
    }

    /**
     * Get or set the WHERE conditions for this statement
     * @param RaiseDbSqlWhere $w (optional) Set the condition for this statement
     * @return RaiseDbSqlWhere
     */
    public function where($w = null){
        if(func_num_args() == 1){
            $this->where = $w;
        }
        return $this->where;
    }

    /**
     * Get or set the row limit
     * @param integer $l (optional) The new limit value
     * @return integer
     */
    public function limit($l = null){
        if(func_num_args() == 1){
            $this->limit = $l;
        }
        return $this->limit;
    }

    /**
     * Get or set the row offset
     * @param integer $o (optional) The new offset value
     * @return integer
     */
    public function offset($o = null){
        if(func_num_args() == 1){
            $this->offset = $o;
        }
        return $this->offset;
    }

    /**
     * Get the collection of RaiseDbSqlJoin statements
     * @return RaiseTypedCollection
     */
    public function join(){
        if(func_num_args() > 0){
            throw new RaiseInvalidArgumentException('RaiseDbSqlQueryCondition::join() does not expect any arguments. ' . func_num_args() . ' argument(s) has been passed in.');
        }
        return $this->join;
    }

    /**
     * Get or set collection of group by fields
     * @return RaiseCollection
     */
    public function group(){
        if(func_num_args() > 0){
            throw new RaiseInvalidArgumentException('RaiseDbSqlQueryCondition::group() does not expect any arguments. ' . func_num_args() . ' argument(s) has been passed in.');
        }
        return $this->group;
    }

    /**
     * Get collection of order by fields
     * @return RaiseTypedCollection
     */
    public function order(){
        if(func_num_args() > 0){
            throw new RaiseInvalidArgumentException('RaiseDbSqlQueryCondition::order() does not expect any arguments. ' . func_num_args() . ' argument(s) has been passed in.');
        }
        return $this->order;
    }

    public function __toString() {
        $q = '';

        if($this->join()->count() > 0){
            foreach($this->join as $j){
                $q .= ' '.$j->__toString();
            }
        }

        if($this->where()){
            $w = $this->where()->__toString();
            if($w){
                $q .= ' WHERE ' . $w;
            }
        }

        if($this->group()->count() > 0){
            $q .= ' GROUP BY ';
            $t = array();
            foreach($this->group() as $f){
                $t[] = (string)$f;
            }
            $q .= implode(', ', $t);
        }

        if($this->order()->count() > 0){
            $q .= ' ORDER BY ';
            $t = array();
            foreach($this->order() as $f){
                $t[] = (string)$f;
            }
            $q .= implode(', ', $t);
        }

        if($this->limit()){

            if($this->offset()){
                $q .= ' LIMIT ' . $this->offset() . ', ' . $this->limit();
            }else{
                $q .= ' LIMIT ' . $this->limit();
            }
        }
        return $q;
    }

}
